"""
物流相关服务
"""
from datetime import datetime
from app.models.logistics import Logistics, LogisticsProvider, LogisticsStatus, TrackingNode
from app.models.order import Order
from app.extensions import db, socketio
from app.utils.errors import NotFoundError, ValidationError

class LogisticsService:
    """物流服务类"""
    
    @staticmethod
    def get_logistics_providers():
        """获取所有物流服务商"""
        return LogisticsProvider.query.all()
    
    @staticmethod
    def get_logistics_provider(provider_id):
        """获取特定物流服务商"""
        provider = LogisticsProvider.query.get(provider_id)
        
        if not provider:
            raise NotFoundError("物流服务商不存在")
        
        return provider
    
    @staticmethod
    def create_logistics_provider(data):
        """创建物流服务商"""
        if not data.get('name'):
            raise ValidationError("请提供物流服务商名称")
        
        try:
            provider = LogisticsProvider(
                name=data.get('name'),
                description=data.get('description'),
                website=data.get('website'),
                contact=data.get('contact'),
                api_key=data.get('api_key'),
                api_url=data.get('api_url')
            )
            
            db.session.add(provider)
            db.session.commit()
            
            return provider
            
        except Exception as e:
            db.session.rollback()
            raise ValidationError(f"创建物流服务商失败: {str(e)}")
    
    @staticmethod
    def update_logistics_provider(provider_id, data):
        """更新物流服务商信息"""
        provider = LogisticsProvider.query.get(provider_id)
        
        if not provider:
            raise NotFoundError("物流服务商不存在")
        
        try:
            if 'name' in data:
                provider.name = data.get('name')
            if 'description' in data:
                provider.description = data.get('description')
            if 'website' in data:
                provider.website = data.get('website')
            if 'contact' in data:
                provider.contact = data.get('contact')
            if 'api_key' in data:
                provider.api_key = data.get('api_key')
            if 'api_url' in data:
                provider.api_url = data.get('api_url')
            
            db.session.commit()
            
            return provider
            
        except Exception as e:
            db.session.rollback()
            raise ValidationError(f"更新物流服务商失败: {str(e)}")
    
    @staticmethod
    def delete_logistics_provider(provider_id):
        """删除物流服务商"""
        provider = LogisticsProvider.query.get(provider_id)
        
        if not provider:
            raise NotFoundError("物流服务商不存在")
        
        # 检查是否有关联的物流单
        if Logistics.query.filter_by(provider_id=provider_id).first():
            raise ValidationError("该物流服务商有关联的物流单，无法删除")
        
        try:
            db.session.delete(provider)
            db.session.commit()
            
            return {"msg": "物流服务商删除成功"}
            
        except Exception as e:
            db.session.rollback()
            raise ValidationError(f"删除物流服务商失败: {str(e)}")
    
    @staticmethod
    def get_logistics_list(user_id=None, page=1, per_page=20, status=None, 
                         tracking_number=None, provider_id=None, 
                         sort_by='created_at', sort_order='desc'):
        """获取物流单列表"""
        query = Logistics.query
        
        # 如果提供了用户ID，只返回该用户关联的物流单
        if user_id:
            # 获取用户的所有订单ID
            user_order_ids = [order.id for order in Order.query.filter_by(user_id=user_id).all()]
            query = query.filter(Logistics.order_id.in_(user_order_ids))
        
        # 过滤条件
        if status:
            query = query.filter_by(status=status)
        
        if tracking_number:
            query = query.filter(Logistics.tracking_number.ilike(f'%{tracking_number}%'))
        
        if provider_id:
            query = query.filter_by(provider_id=provider_id)
        
        # 排序
        if sort_order == 'desc':
            query = query.order_by(getattr(Logistics, sort_by).desc())
        else:
            query = query.order_by(getattr(Logistics, sort_by).asc())
        
        # 分页
        pagination = query.paginate(page=page, per_page=per_page)
        
        return pagination
    
    @staticmethod
    def get_logistics_detail(logistics_id, user_id=None):
        """获取物流单详情"""
        logistics = Logistics.query.get(logistics_id)
        
        if not logistics:
            raise NotFoundError("物流单不存在")
        
        # 如果提供了用户ID，确保该用户有权限查看此物流单
        if user_id:
            order = Order.query.get(logistics.order_id)
            if not order or order.user_id != user_id:
                raise ValidationError("无权限查看此物流单")
        
        return logistics
    
    @staticmethod
    def create_logistics(data):
        """创建物流单"""
        if not data.get('order_id') or not data.get('provider_id'):
            raise ValidationError("请提供订单ID和物流服务商ID")
        
        # 验证订单存在
        order = Order.query.get(data.get('order_id'))
        if not order:
            raise NotFoundError("订单不存在")
        
        # 验证物流服务商存在
        provider = LogisticsProvider.query.get(data.get('provider_id'))
        if not provider:
            raise NotFoundError("物流服务商不存在")
        
        # 检查是否已有关联物流单
        if Logistics.query.filter_by(order_id=data.get('order_id')).first():
            raise ValidationError("该订单已有关联的物流单")
        
        try:
            logistics = Logistics(
                order_id=data.get('order_id'),
                provider_id=data.get('provider_id'),
                tracking_number=data.get('tracking_number'),
                status=LogisticsStatus.PROCESSING.value,
                shipping_address=data.get('shipping_address') or order.shipping_address,
                estimated_delivery=data.get('estimated_delivery')
            )
            
            db.session.add(logistics)
            db.session.flush()  # 获取物流单ID
            
            # 创建初始跟踪节点
            tracking_node = TrackingNode(
                logistics_id=logistics.id,
                status=LogisticsStatus.PROCESSING.value,
                location=data.get('location', '物流中心'),
                description="物流单已创建"
            )
            
            db.session.add(tracking_node)
            db.session.commit()
            
            # 通过WebSocket发送物流状态更新通知
            socketio.emit('logistics_update', {
                'logistics_id': logistics.id,
                'order_id': logistics.order_id,
                'status': logistics.status,
                'tracking_number': logistics.tracking_number
            })
            
            return logistics
            
        except Exception as e:
            db.session.rollback()
            raise ValidationError(f"创建物流单失败: {str(e)}")
    
    @staticmethod
    def update_logistics_status(logistics_id, status, location=None, description=None):
        """更新物流状态"""
        logistics = Logistics.query.get(logistics_id)
        
        if not logistics:
            raise NotFoundError("物流单不存在")
        
        # 验证状态值是否有效
        if status not in [s.value for s in LogisticsStatus]:
            raise ValidationError("无效的物流状态")
        
        try:
            # 更新物流状态
            logistics.status = status
            
            # 创建新的跟踪节点
            tracking_node = TrackingNode(
                logistics_id=logistics.id,
                status=status,
                location=location or '',
                description=description or ''
            )
            
            db.session.add(tracking_node)
            db.session.commit()
            
            # 通过WebSocket发送物流状态更新通知
            from app.schemas.logistics import TrackingNodeSchema
            socketio.emit('logistics_update', {
                'logistics_id': logistics.id,
                'order_id': logistics.order_id,
                'status': logistics.status,
                'tracking_number': logistics.tracking_number,
                'tracking_node': TrackingNodeSchema().dump(tracking_node)
            })
            
            return logistics
            
        except Exception as e:
            db.session.rollback()
            raise ValidationError(f"更新物流状态失败: {str(e)}")
    
    @staticmethod
    def get_tracking_history(logistics_id, user_id=None):
        """获取物流跟踪历史"""
        logistics = Logistics.query.get(logistics_id)
        
        if not logistics:
            raise NotFoundError("物流单不存在")
        
        # 如果提供了用户ID，确保该用户有权限查看此物流单
        if user_id:
            order = Order.query.get(logistics.order_id)
            if not order or order.user_id != user_id:
                raise ValidationError("无权限查看此物流单")
        
        # 获取跟踪节点并按时间降序排序
        tracking_nodes = TrackingNode.query.filter_by(
            logistics_id=logistics_id
        ).order_by(TrackingNode.created_at.desc()).all()
        
        return tracking_nodes 